package com.coamc.xlsunit;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

/**
 * 变量表，用来处理一个单元测试里的所有变量
 * @author xiandafu
 *
 */
public class VariableTable {
	Map<String, Object> vars = new HashMap<String, Object>();
	Map<String, Function> fns = new HashMap<String, Function>();
	XLSParser xlsParser = null;

	public VariableTable() {
		initDefaultFns();
	}

	/**
	 * 支持从excel中查找变量，比如test.user,也可以对输入工作表里的数据库表数据进行查找，如
	 * $AB$32,代表32行AB列
	 * @param name
	 * @return
	 */
	public Object find(String name) {
		return find(name, false);
	}


	public Object find(String name, boolean allowNoExit) {
		if (name.startsWith("fn.")) {
			return getFnValue(name);
		} else if (name.startsWith("$")) {
			// 指向excel 某个位置，如$B$9
			return getCellValue(name);
		}
		boolean contain = vars.containsKey(name);
		if (!allowNoExit && !contain) {
			throw new RuntimeException("no value " + name + " in Variable Table");
		}
		Object value = vars.get(name);
		return value;

	}

	public boolean contain(String name) {
		if (name.startsWith("fn.")) {
			return true;
		} else {
			return vars.containsKey(name);
		}

	}

	public void setXLSParser(XLSParser parser) {
		this.xlsParser = parser;
	}

	private Object getCellValue(String name) {
		String[] array = name.split("\\$");
		String row = array[2];
		String col = array[1];
		return this.xlsParser.getCeelValue(col, row);

	}

	private Object getFnValue(String name) {
		String fnName = name.substring(3);
		Function fn = fns.get(fnName);
		if (fn == null) {
			throw new RuntimeException("未找到方法名" + fnName);

		}
		return fn.value(fnName);
	}

	public void add(String name, Object value) {
		vars.put(name, value);
	}

	public Map<String, Object> findScope(String scope) {
		if (StringUtils.isEmpty(scope)) {
			return this.vars;
		}
		String prefix = scope + ".";
		Map<String, Object> map = new HashMap<String, Object>();
		for (Entry<String, Object> entry : vars.entrySet()) {
			String key = entry.getKey();
			if (key.startsWith(prefix)) {
				// int index = key.indexOf(prefix);
				String attrName = key.substring(prefix.length());
				map.put(attrName, entry.getValue());
			}
		}
		return map;

	}

	@Override
	public String toString() {
		return vars.toString();
	}

	private void initDefaultFns() {
		DateFunction df = new DateFunction();
		SeqFunction seqFn = new SeqFunction();
		fns.put("date", df);
		fns.put("timestamp", df);
		fns.put("sqlDate", df);
		fns.put("seq", seqFn);


	}

	static public class DateFunction implements Function {

		@Override
		public Object value(String name) {
			if (name.equals("date")) {
				return new Date();
			} else if (name.equals("timestamp")) {
				return new Timestamp(System.currentTimeMillis());
			} else if (name.equals("sqlDate")) {
				return new java.sql.Date(System.currentTimeMillis());
			} else {
				throw new RuntimeException("不支持的方法调用" + name);
			}
		}

	}


	static public class SeqFunction implements Function {
		// 对于模拟生成id，从较大的数模拟器会减少冲突
		public static long seq = 100000;

		@Override
		public Object value(String name) {
			return seq++;
		}

	}


	public Map<String, Function> getFns() {
		return fns;
	}

	public String findString(String name) {
		Object o = this.find(name);
		if (o == null) {
			return null;
		} else if (o instanceof String) {
			return (String) o;
		} else {
			return o.toString();
		}
	}

	public Long findLong(String name) {
		Object o = this.find(name);
		if (o == null) {
			return null;
		} else if (o instanceof Long) {
			return (Long) o;
		} else if (o instanceof Number) {
			return ((Number) o).longValue();
		} else {
			throw new RuntimeException("Long expectd,but " + o);
		}
	}

	public Integer findInteger(String name) {
		Object o = this.find(name);
		if (o == null) {
			return null;
		} else if (o instanceof Integer) {
			return (Integer) o;
		} else if (o instanceof Number) {
			return ((Number) o).intValue();
		} else {
			throw new RuntimeException("Integer expectd,but " + o);
		}
	}


}
